home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World Komputer 2010 April
/
PCWorld0410.iso
/
pluginy Firefox
/
11255
/
11255.xpi
/
chrome
/
content
/
model
/
Model.js
< prev
Wrap
Text File
|
2009-12-17
|
23KB
|
591 lines
/* ***** BEGIN LICENSE BLOCK *****
*
* Pearltrees add-on AMO, Copyright(C), 2009, Broceliand SAS, Paris, France
* (company in charge of developing Pearltrees)
*
* This file is part of ΓÇ£Pearltrees add-on AMOΓÇ¥.
*
* Pearltrees add-on AMO is free software: you can redistribute it and/or modify it under the
* terms of the GNU General Public License version 3 as published by the Free Software Foundation.
*
* Pearltrees add-on AMO is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with Pearltrees add-on AMO.
* If not, see <http://www.gnu.org/licenses/>
*
* ***** END LICENSE BLOCK ***** */
/////////////////////////////////////////////////////////////////////////////////
// Model class
// Handle server connections and password managers
//
// Classes:
//
// BRO_model Communication with the server
// BRO_JSON Handle JSON objects
//
/////////////////////////////////////////////////////////////////////////////////
/**
* Communication with the server.
*/
var BRO_model = {
_json:null,
_serviceUrl:null,
_treeList:null, // treeItem: treeID, title, pearlCount, lastUpdate
_historyList:null, // historyItem: id, name, pearlCount, lastUpdate
_currentUser:null, // user: userID, userDB, username, rootTreeID
_skipNotificationIfNotLoggedOnNextValidation:false,
getServiceUrl: function(){return this._serviceUrl},
getTreeList: function(){return this._treeList},
setTreeList: function(value){this._treeList = value},
getHistoryList: function(){return this._historyList},
setHistoryList: function(value){this._historyList = value},
getCurrentUser: function(){return this._currentUser},
setCurrentUser: function(value){this._currentUser = value},
getRootTree: function () {
if(!this._treeList || !this._currentUser) return null;
var treeListLength = this._treeList.length;
for (var i = 0; i < treeListLength; i++) {
if (this._treeList[i].treeID == this._currentUser.rootTreeID) {
return this._treeList[i];
}
}
return null;
},
START_HISTORY_SUCCESS:0,
START_HISTORY_SUCCESS_ON_SWITCH:1,
START_HISTORY_ERROR_INVALID_TREE:2,
START_HISTORY_ERROR_TREE_DELETED:3,
START_HISTORY_ERROR_IS_NOT_OWNER:4,
skipNextRequestValidation:false,
/**
* Init server connection parameters
* @todo Should be moved in a config file
*/
init: function() {
this._treeList = null;
this._historyList = null;
this._currentUser = null;
this._serviceUrl = BRO_SERVICE_FF_URL;
// Try to use FF3 native json component
if(Components.classes["@mozilla.org/dom/json;1"]) {
this._json = Components.classes["@mozilla.org/dom/json;1"]
.createInstance(Components.interfaces.nsIJSON);
}else{
this._json = JSONFF2;
}
},
/**
* Create a GET XMLHttpRequest object with a valid cookie.
* @param string url
* @return XMLHttpRequest
*/
createXMLHttpRequest:function(url) {
var req = new XMLHttpRequest();
req.open('GET', url, true);
return req;
},
notifyDownloadToAMO:function() {
var url = BRO_AMO_FILE_URL + "?src=" + BRO_AMO_SOURCE;
var req = this.createXMLHttpRequest(url);
req.onreadystatechange = function (e) {
if (req.readyState == 4) {
BRO_toolbar.onDownloadNotifiedToAMO();
}
}
req.send(null);
},
notifyActiveUserToAMO:function() {
var extension = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager)
.getItemForID(BRO_ADDON_ID);
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
.getService(Components.interfaces.nsIXULAppInfo);
var xulRuntime = Components.classes["@mozilla.org/xre/app-info;1"]
.getService(Components.interfaces.nsIXULRuntime);
var useragentPrefs = Components.classes["@mozilla.org/preferences-service;1"]
.getService(Components.interfaces.nsIPrefService)
.getBranch("general.useragent.");
var reqVersion = "%"; // request last version
var version = extension.version; // current addon version (e.g: 5.0.9)
var id = extension.id; // addon id (e.g: collector@broceliand.fr)
var appID = appInfo.ID; // Firefox Application ID
var appVersion = appInfo.version; // Firefox version (e.g: 3.6b4)
var locale = useragentPrefs.getCharPref("locale"); // lang (e.g: en_US)
var appOS = xulRuntime.OS; // OS family (e.g: WINNT)
var appABI = xulRuntime.XPCOMABI; // compiler info
var maxAppVersion = extension.maxAppVersion; // addon max version supported
var status = "userEnabled"; // is the addon enabled
if(typeof(Application) != 'undefined') {
var extensions = Application.extensions.all;
for(var i=0; i<extensions.length; i++) {
var ext = extensions[i];
if(ext.id == id) {
status = (ext.enabled)?"userEnabled":"userDisabled";
}
}
}
var url = BRO_AMO_VERSION_CHECK +
"?reqVersion="+reqVersion+
"&version="+version+
"&id="+id+
"&appID="+appID+
"&appVersion="+appVersion+
"&locale="+locale+
"&appOS="+appOS+
"&appABI="+appABI+
"&maxAppVersion="+maxAppVersion+
"&status="+status;
var req = this.createXMLHttpRequest(url);
req.onreadystatechange = function (e) {
if (req.readyState == 4) {
BRO_toolbar.onActiveUserNotifiedToAMO();
}
}
req.send(null);
},
/**
* Start a new history
*/
start:function(newTreeName) {
var action = 'start';
var params = '?newTreeName='+newTreeName
+'&time='+BRO_tools.getTime();
BRO_log.log('start new history ('+newTreeName+')');
var req = this.createXMLHttpRequest(this._serviceUrl+action+params);
req.onreadystatechange = function (e) {
if (req.readyState == 4) {
if(BRO_model.validateResponse(req,true)) {
if(req.responseText) {
//BRO_log.log('Started !'+req.responseText);
}
}
};}
req.send(null);
},
/**
* continue an existing history
*/
continueHistory:function(treeID, historyID) {
var action = 'continue';
var params = '?time='+BRO_tools.getTime()
+'&treeID='+treeID
+'&historyID='+historyID;
BRO_log.log('continue history ('+treeID+', '+historyID+')');
var req = this.createXMLHttpRequest(this._serviceUrl+action+params);
req.onreadystatechange = function (e) {
if (req.readyState == 4) {
if(BRO_model.validateResponse(req,true) && req.responseText) {
if(req.responseText == BRO_model.START_HISTORY_ERROR_TREE_DELETED) {
BRO_toolbar.showTreeDeletedMessage();
}else if(req.responseText != BRO_model.START_HISTORY_SUCCESS) {
BRO_toolbar.errorOnContinueHistory(req.responseText);
}
}
};}
req.send(null);
},
addComment:function(url, browserUID, time, comment) {
var action = 'addcomment';
var params = '?url='+encodeURIComponent(url)
+'&browserUID='+browserUID
+'&time='+time
+'&comment='+comment;
BRO_log.log('add comment ('+url+', '+browserUID+', '+time+', '+comment+')');
var req = this.createXMLHttpRequest(this._serviceUrl+action+params);
req.onreadystatechange = function (e) {
if (req.readyState == 4) {
BRO_model.validateResponse(req,true);
};}
req.send(null);
},
/**
* Add a new pearl
*/
add:function(url, title, method, browserUID, time, isStart, treeID, newTreeName, historyID) {
var action = 'add';
var title = encodeURIComponent(title.replace(/^\s*|\s*$/g,''));
var treeID = (!isStart && BRO_inButtonController._selectedTree)?BRO_inButtonController._selectedTree.treeID:null;
var historyID = (!isStart && BRO_inButtonController._selectedHistory)?BRO_inButtonController._selectedHistory.id:null;
var params = '?url='+encodeURIComponent(url)
+'&title='+title
+'&method='+method
+'&browserUID='+browserUID
+'&time='+time;
if(isStart) {
params += '&isStart='+isStart;
params += '&newTreeName='+newTreeName;
}
if(treeID) params += '&treeID='+treeID;
if(historyID) params += '&historyID='+historyID;
// If the method sent will create a pearl we run an effect
// @todo run the effect on server response
if(method != BRO_METHOD_TAB_CREATED) {
BRO_buttonEffectHelper.runIsRecordingEffect();
}
BRO_log.log('add ('+url+', '+title+', '+method+' , '+browserUID+ ', '+time+', '+isStart+', '+treeID+', '+newTreeName+', '+historyID+')');
var req = this.createXMLHttpRequest(this._serviceUrl+action+params);
req.onreadystatechange = function (e) {
if (req.readyState == 4) {
if(BRO_model.validateResponse(req,true) && req.responseText) {
// If recording in a deleted tree
if(req.responseText == BRO_model.START_HISTORY_ERROR_TREE_DELETED) {
BRO_toolbar.showTreeDeletedMessage();
}
// If a server error occured
else if(req.responseText != BRO_model.START_HISTORY_SUCCESS && req.responseText != BRO_model.START_HISTORY_SUCCESS_ON_SWITCH) {
BRO_toolbar.errorOnContinueHistory(req.responseText);
}
}
};}
req.send(null);
},
/**
* Validate URLs for inserts
* @param string url
*/
isValidUrl:function(url) {
if(!url
|| url == ''
|| url == 'about:blank'
|| url.lastIndexOf(BRO_PUBLIC_URL) == 0
|| url.lastIndexOf('http://www.broceliand.fr') ==0
|| (url.lastIndexOf('http://www.pearltrees.com') ==0
&& url.lastIndexOf('http://www.pearltrees.com/blog') == -1
&& url.lastIndexOf('http://www.pearltrees.com/forum') == -1)
|| url.lastIndexOf('http://localhost') ==0
|| url.lastIndexOf('http://127.0.0.1') ==0
|| url.substring(0,4) != 'http'){
return false;
}
return true;
},
/**
* Clear the current history if exist.
* Called when the application stop.
*/
clear:function() {
var action = 'clear';
var params = '?time='+BRO_tools.getTime();
BRO_log.log('clear');
var req = this.createXMLHttpRequest(this._serviceUrl+action+params);
req.onreadystatechange = function (e) {
if (e && e.readyState == 4) {
//...
};
}
req.send(null);
},
getTreesAndCurrentUser:function(skipNotificationIfNotLogged) {
var action = 'gettreesandcurrentuser';
var params = '';
this._skipNotificationIfNotLoggedOnNextValidation = skipNotificationIfNotLogged;
BRO_log.log('load trees and current user');
var req = this.createXMLHttpRequest(this._serviceUrl+action+params);
req.onreadystatechange = function (e) {
if (req.readyState == 4) {
if(BRO_model.validateResponse(req)) {
if (req.responseText) {
var response = BRO_model._json.decode(req.responseText);
var currentUserResponse = response.currentUser;
BRO_model.updateCurrentUser(currentUserResponse);
var listChanged = false;
var treeListResponse = response.treeList;
var historyListResponse = response.historyList;
if(!BRO_model._treeList || !BRO_model.areTreeListsEquals(treeListResponse,BRO_model._treeList)) {
BRO_model._treeList = BRO_model.mergeLocalTreeListWithServerList(treeListResponse);
BRO_windowManager.setTreeList(BRO_model._treeList);
// must be called after currentUser being set
BRO_toolbar.saveRootTreeIntoPreferences(BRO_model.getRootTreeFromTreeList());
BRO_toolbar.saveDropZoneIntoPreferences(BRO_model.getDropZoneFromTreeList());
listChanged = true;
}
if(!BRO_model._historyList || !BRO_model.areHistoryListsEquals(historyListResponse,BRO_model._historyList)) {
BRO_model._historyList = BRO_model.mergeLocalHistoryListWithServerList(historyListResponse);
BRO_windowManager.setHistoryList(BRO_model._historyList);
listChanged = true;
}
if(listChanged) {
BRO_inButtonController.onTreeListLoaded();
}
else{
BRO_inButtonController.onTreeListNotChanged();
}
}
}
}
}
req.send(null);
},
getRootTreeFromTreeList:function() {
var treeList = BRO_model.getTreeList();
var currentUser = BRO_model.getCurrentUser();
if(!treeList || !currentUser) return;
for(var i=0; i < treeList.length; i++) {
if(treeList[i].treeID == currentUser.rootTreeID) {
return treeList[i];
}
}
return null;
},
getDropZoneFromTreeList:function() {
var treeList = BRO_model.getTreeList();
var currentUser = BRO_model.getCurrentUser();
if(!treeList || !currentUser) return;
for(var i=0; i < treeList.length; i++) {
if(treeList[i].treeID == currentUser.dropZoneID) {
return treeList[i];
}
}
return null;
},
updateCurrentUser:function(value) {
if(!BRO_model.areUserEquals(value, BRO_model._currentUser)) {
BRO_model._currentUser = value;
BRO_windowManager.setCurrentUser(BRO_model._currentUser);
if(BRO_model._currentUser) {
BRO_toolbar.saveCurrentUserIntoPreferences(BRO_model._currentUser);
}
}
if(BRO_toolbar.getOptionWindow() && BRO_toolbar.getOptionWindow().document) {
var statusDescription = BRO_toolbar.getOptionWindow().document.getElementById('BRO_statusDescription');
if(statusDescription) {
if(BRO_toolbar.isUserLogged && BRO_model._currentUser) {
statusDescription.value = "signed as "+BRO_model._currentUser.username;
}else{
statusDescription.value = "signed out";
}
}
}
},
areTreeListsEquals:function(list1, list2) {
if(!list1 && !list2) return true;
if((!list1 && list2) || (list1 && !list2)) return false;
var list1Length = list1.length;
var list2Length = list2.length;
if(list1Length != list2Length) return false;
for(var i=0; i < list1Length;i++) {
if(list1[i].treeID != list2[i].treeID) {
return false;
}
else if(list1[i].title != list2[i].title) {
return false;
}
else if(list1[i].lastUpdate != list2[i].lastUpdate) {
return false;
}
}
return true;
},
mergeLocalTreeListWithServerList:function(serverTreeList) {
var localTreeList = BRO_model._treeList;
if(!localTreeList) return serverTreeList;
if(!serverTreeList) return null;
var serverTreeListLength = serverTreeList.length;
var localTreeListLength = localTreeList.length;
// Don't update trees if we don't need to
for(var i=0; i < serverTreeListLength; i++) {
for(var j=0; j < localTreeListLength; j++) {
if(serverTreeList[i].treeID == localTreeList[j].treeID
&& serverTreeList[i].title == localTreeList[j].title
&& serverTreeList[i].lastUpdate == localTreeList[j].lastUpdate) {
serverTreeList[i] = localTreeList[j];
break;
}
}
}
return serverTreeList;
},
mergeLocalHistoryListWithServerList:function(serverHistoryList) {
var localHistoryList = BRO_model._treeList;
if(!localHistoryList) return serverHistoryList;
if(!serverHistoryList) return null;
var serverHistoryListLength = serverHistoryList.length;
var localHistoryListLength = localHistoryList.length;
// Don't update trees if we don't need to
for(var i=0; i < serverHistoryListLength; i++) {
for(var j=0; j < localHistoryListLength; j++) {
if(serverHistoryList[i].id == localHistoryList[j].id
&& serverHistoryList[i].name == localHistoryList[j].name
&& serverHistoryList[i].lastUpdate == localHistoryList[j].lastUpdate) {
serverHistoryList[i] = localHistoryList[j];
break;
}
}
}
return serverHistoryList;
},
areHistoryListsEquals:function(list1, list2) {
if(!list1 && !list2) return true;
if((!list1 && list2) || (list1 && !list2)) return false;
var list1Length = list1.length;
var list2Length = list2.length;
if(list1Length != list2Length) return false;
for(var i=0; i < list1Length;i++) {
if(list1[i].id != list2[i].id || list1[i].name != list2[i].name) return false;
}
return true;
},
areUserEquals:function(user1, user2) {
if(!user1 && !user2) return true;
if((!user1 && user2) || (user1 && !user2)) return false;
return (user1.userID == user2.userID)?true:false;
},
/**
* Validate XMLHttpRequest reponse and handle errors
* @param resp XMLHttpRequest response
*/
validateResponse:function(resp, retryOnError) {
if(!resp) return false;
var status = null;
var responseText = null;
try{
status = resp.status;
responseText = resp.responseText;
}
catch(e){}
// Valid
if(status == 200 || this.skipNextRequestValidation) {
this.skipNextRequestValidation = false;
BRO_toolbar.isUserLogged = true;
return true;
}
// No session auth is opened.
else if(status == 303) {
BRO_log.log("server 303 Not Logged");
BRO_toolbar.isUserLogged = false;
// Stop all recording actions.
BRO_toolbar.setRecording(false);
if(!BRO_toolbar.isThirdPartyCookiesEnabled()) {
if(BRO_toolbar.isUserWantToEnableThirdPartyCookies()){
BRO_toolbar.enableThirdPartyCookies();
if(retryOnError) BRO_ButtonsHandler.startRecording();
}
}
else if(!this._skipNotificationIfNotLoggedOnNextValidation) {
if(BRO_toolbar.isUserWantToLogin()==true) {
BRO_toolbar.showLoginForm();
}
}
BRO_model.resetModel();
}
// Unauthorized WWW-Authenticate
else if(status == 401){
if(BRO_toolbar.isRecording) {
BRO_toolbar.setRecording(false);
}
}
else {
BRO_log.log("Invalid server response. HTTP status: "+status+" "+responseText);
BRO_log.error(BRO_locale.getString('popup.error.responseError'));
}
this.skipNextRequestValidation = false;
return false;
},
// @todo refactor
resetModel:function() {
// update model
BRO_model.updateCurrentUser(null);
BRO_model.setTreeList(null);
BRO_windowManager.setTreeList(null);
BRO_model.setHistoryList(null);
BRO_windowManager.setHistoryList(null);
// update toolbar state
BRO_toolbar.setRecording(false);
// update ButtonsHandler
BRO_inButtonController._selectedTree = null;
BRO_inButtonController._selectedHistory = null;
BRO_inButtonController._selectedNewHistory = null;
BRO_inButtonController.initTreeList();
BRO_toolbar.lastUrlRecorded = null;
BRO_recordButtonController.refreshRecordButtonLabel(BRO_toolbar.isRecording);
}
}